package bubblesn;


/**
 * Abstract class to represent sorting network.
 * @author Rafalmag
 */
public abstract class SortingNetwork{
	// for storing representation of bubble sorting network
	protected Gate[][] network;
	public PathLengths pathlengths;
	protected int inputLines;
	protected int cols;
	
	/**
	 * Constructor
	 * @param inLines describes size of input
	 * @throws Exception when inLines<2
	 */	
	public SortingNetwork(int inLines) throws Exception{
		if(inLines<2)
			throw new Exception();
		
		this.inputLines=inLines;
		this.pathlengths=new PathLengths(inLines);
		this.cols=2*this.inputLines-2;
		this.network = new Gate[this.inputLines][cols];
		fillNet();
	}
	
	/**
	 * Initializes network
	 */	
	private void fillNet(){
		if(inputLines==0){
			return;
		}else{
			// initialize array
			for(int i=0; i<inputLines; i++){
				for(int j=0; j<cols; j++){
					if(j!=cols-1){
						network[i][j]=Gate.path;
					}else{
						network[i][j]=Gate.output;
					}
				}
			}
			
			for(int i=0; i<inputLines-1; i++){
				if(i==0){
					network[0][0]=Gate.or;
					network[1][0]=Gate.and;
					//printNetwork();
				}else{
					//adds 2 ors, 2 ands
					for(int j=0; j<=i;j++){
						network[i  -j][i+j]=Gate.or;
						network[i+1-j][i+j]=Gate.and;
						//printNetwork();
					}
				}
			}
		}
		//printNetwork();
	}
	
	/**
	 * Prints graphical representation of network
	 */
	void printNetwork(){
		if(true){
			for(int i=0; i<inputLines; i++){
				for(int j=0; j<cols; j++){
					switch(network[i][j]){
						case and:
							System.out.print("a");
							break;
						case or:
							System.out.print("o");
							break;
						case path:
							System.out.print("-");
							break;
						case output:
							System.out.print("q");
							break;
						default:
							System.out.print("z");
					}
				}
				System.out.println();
			}
		}
	}
	
	/**
	 * Makes all possible transitions and adds their lengths to pathlengths
	 * @param threads number of threads to use to compute transitions
	 */		
	public abstract void doAllTransitions(final int threads);
	
	/**
	 * Makes single transition in sorting network
	 * @param from - type of gate, which we come from
	 * @param to - end coordinate
	 * @param gates - how many gates have been visited
	 */	
	public abstract void transition(Gate from, Coordinate to, int gates);
	
	/**
	 * Prints output 
	 */
	public void printOutput(){
		int maxpath=pathlengths.getMaxPath();
		// first row:
		System.out.println("output\tpaths of length");
		System.out.print("\t");
		for(int i=1; i<maxpath; i++){
			System.out.print(i+"\t");
		}
		System.out.println();

		// next rows
		for(int i=0; i<inputLines; i++){
			System.out.print("T"+(i+1)+"\t");
			for(int j=1; j<maxpath; j++){
				System.out.print(pathlengths.get(i, j)+"\t");
			}
			System.out.println();
		}
	}
	
}
